package cn.wenlihelp.controller;

import cn.wenlihelp.annotations.NoLogin;
import cn.wenlihelp.bean.Account;
import cn.wenlihelp.bean.ResourceType;
import cn.wenlihelp.bean.Resources;
import cn.wenlihelp.bean.Role;
import cn.wenlihelp.config.Constants;
import cn.wenlihelp.config.SystemProperty;
import cn.wenlihelp.service.LoginService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@SessionAttributes({Constants.SESSION_LOGIN_STATUS, Constants.SESSION_MENU, Constants.SESSION_RESOURCES, Constants.SESSION_ROLE})
public class LoginController {
    @Resource
    private LoginService loginService;

    @Resource
    private SystemProperty systemProperty;

    @NoLogin
    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @NoLogin
    @PostMapping("/login")
    public String login(Account account, ModelMap modelMap) {
        Account loginAccount = loginService.login(account);
        //获取账号所关联的角色
        Set<Role> roles = loginAccount.getRoles();
        //遍历角色获取角色关联的资源
        Set<Resources> resources = new HashSet<>();
        for (Role role : roles) {
            Set<Resources> roleResources = role.getResources();
            for (Resources roleResource : roleResources) {
                getResources(roleResource, resources);
            }
        }
        Map<Integer, Resources> resourcesMap = new HashMap<>();
        Set<Resources> menus = new HashSet<>();
        for (Resources resource : resources) {
            resourcesMap.put(resource.getId(), resource);
            if (resource.getPid() == -1
                    && Optional.ofNullable(resource)
                    .map(Resources::getResourceType)
                    .map(ResourceType::getCode)
                    .map(code -> code.equals(systemProperty.getResourceTypeMenuCode()))
                    .orElse(false)) {
                menus.add(resource);
            }
        }
        for (Resources resource : resources) {
            if (resource.getPid() != -1) {
                Resources parent = resourcesMap.get(resource.getPid());
                parent.getChilds().add(resource);
            }
        }
        if (loginAccount != null) {
            modelMap.addAttribute(Constants.SESSION_LOGIN_STATUS, loginAccount);
            modelMap.addAttribute(Constants.SESSION_MENU, menus);
            modelMap.addAttribute(Constants.SESSION_RESOURCES, resources.stream().map(Resources::getCode).collect(Collectors.toSet()));
            modelMap.addAttribute(Constants.SESSION_ROLE, roles.stream().map(Role::getCode).collect(Collectors.toSet()));
            return "index";
        }
        return "login";
    }

    @RequestMapping("/logout")
    public String logout(SessionStatus sessionStatus) {
        sessionStatus.setComplete();
        return "login";
    }

    private void getResources(Resources resources, Set<Resources> resourcesSet) {
        resourcesSet.add(resources);
        if (!resources.getChilds().isEmpty()) {
            for (Resources resourcesChild : resources.getChilds()) {
                getResources(resourcesChild, resourcesSet);
            }
        }
    }
}
